package id.mankel.commons.mybatis;

import org.apache.ibatis.annotations.*;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;

public interface BaseMapper {

    String CREATED_BY   = "created_by";
    String CREATED_TIME = "created_time";
    String UPDATED_BY   = "updated_by";
    String UPDATED_TIME = "updated_time";

    /**
     * For SQL Server, as it cannot return multi-row ids from one insert SQL.
     * @param insert the mapper insert method
     * @param list the list of being inserted
     * @param getKey the getter of the bean
     * @param setKey the setter of the bean
     * @param <T> bean type
     * @return number of rows inserted
     */
    static <T> int setKeys(Supplier<Integer> insert, List<T> list, Function<T, Integer> getKey, BiConsumer<T, Integer> setKey) {
        Integer i = insert.get();
        int key = getKey.apply(list.get(0)) - list.size() + 1;
        for (T t : list) {
            setKey.accept(t, key++);
        }
        return i;
    }

    /**
     * Batch insert with key generator.
     * @param tableName table name
     * @param keyProperty Java bean property representing the primary key of the table
     * @param columns column and property mappings
     * @param list the data to insert
     * @return number of rows inserted
     */
    @Options(useGeneratedKeys = true, keyProperty = "list.${keyProperty}")
    @InsertProvider(value = BaseSqlProvider.class, method = "insert")
    int insertBatchWithKeyGenerator(
            @Param(BaseSqlProvider.TABLE_NAME) String tableName,
            @Param(BaseSqlProvider.KEY_PROPERTY) String keyProperty,
            @Param(BaseSqlProvider.FOR_EACH_COLUMNS) ResultMapper[] columns,
            @Param(BaseSqlProvider.FOR_EACH_LIST) List<?> list);

    /**
     * Batch insert.
     * @param tableName table name
     * @param columns column and property mappings
     * @param list the data to insert
     * @return number of rows inserted
     */
    @InsertProvider(value = BaseSqlProvider.class, method = "insert")
    int insertBatch(
            @Param(BaseSqlProvider.TABLE_NAME) String tableName,
            @Param(BaseSqlProvider.FOR_EACH_COLUMNS) ResultMapper[] columns,
            @Param(BaseSqlProvider.FOR_EACH_LIST) List<?> list);

    /**
     * Batch update.
     * @param tableName table name
     * @param key column and property key mapping
     * @param columns column and property mappings
     * @param list the data to update
     * @return number of rows updated
     */
    @UpdateProvider(value = BaseSqlProvider.class, method = "update")
    int updateBatch(
            @Param("tableName") String tableName,
            @Param("key") ResultMapper key,
            @Param("columns") ResultMapper[] columns,
            @Param("list") List<?> list);

    /**
     * Deletes table rows by column.
     * @param tableName table name
     * @param columnName column name
     * @param list column values
     * @return number of rows deleted
     */
    @DeleteProvider(value = BaseSqlProvider.class, method = "delete")
    int deleteBatch(
            @Param(BaseSqlProvider.TABLE_NAME) String tableName,
            @Param(BaseSqlProvider.COLUMN_NAME) String columnName,
            @Param(BaseSqlProvider.FOR_EACH_LIST) List<?> list);

}
